<!--
查询表单，一般配合表格使用
最后修改：20220225
作者：ljy
一、用法
（一）基本用法
1.1 引入组件的方式
import TableQuery from '@/components/TableQuery.vue';
1.2 使用方式
<TableQuery
      :query="query"
      :loadTableList="loadTableList"
      :clearQuery="clearQuery"
      :queryForm="queryForm"
    />
1.3 参数说明：
(1)query、loadTableList和clearQuery的详细说明参照文件'@/api/uem/useTableList.ts'，为表格封装的必备元素
(2)queryForm是用来组成表单内元素的数组
const queryForm=[
  { // 文本框
    prop: 'username',// 传递参数的model名字
    label: '账号', //表单的label信息
    placeholder:'请输入账户名', //可选：表单内元素的placeholder提示信息，如果缺省该条件，则表单元素的placeholder提示信息默认为是label
  },
  { // 文本框
    prop: 'nickName',
    label: '网名'
  },
  { // select 下拉框
    prop: 'sex',
    label: '性别',
    placeholder:'请选择性别',
    list: [
      {
        value: 0, // 对应option的value属性
        label: '未选择' // 对应option的label属性
      },
      {
        value: 1,
        label: '男'
      },
      {
        value: 2,
        label: '女'
      }
    ]
  }
  ];
（二)查询表单插槽
2.1 说明
如果queryForm不能满足全部的查询表单要求，则可以通过插槽来定制开发
2.2.用法
<TableQuery
  :query="query"
  :loadTableList="loadTableList"
  :clearQuery="clearQuery"
  :queryForm="queryForm"
>
  <template #left>
    <el-form-item label="性别">
      <el-input v-model="query.sex"></el-input>
    </el-form-item>
  </template>
  <template #right>
    <el-form-item label="状态">
      <el-input v-model="query.status"></el-input>
    </el-form-item>
  </template>
</TableQuery>
2.3 标签说明
（1）<template #left></template>
主要用于生成在queryForm渲染生成的表单元素左边
（2）<template #right></template>
主要用于生成在queryForm渲染生成的表单元素右边，在按钮左边。
（3）插槽中v-model绑定的参数都应该用query开头，如果复杂点可以如下：query.user.sex

-->
<template>
    <!--搜索栏-->
    <el-form :model="tableQuery"  :inline="true" style="text-align: left;" class="demo-form-inline">
      <!--表单左边的插槽-->
      <slot name="left" :data="query">
      </slot>
      <template
        v-for="(item,index) in formHeadersVisible"
        :key="index"
        >
        <el-form-item
          :label="item.label"
        >
          <!--自定义插槽，在父组件自行进行创建-->
          <span v-if="item.type === 'custom'">
              <slot :name="item.prop">
              </slot>
          </span>
          <!--如果是普通选择框-->
          <el-select
            v-else-if="item.list&&item.list.length"
            v-model="tableQuery[item.prop]"
            clearable
            :placeholder="`${item.placeholder?item.placeholder:item.label}`"
          >
            <el-option
              v-for="(item1,index1) in item.list"
              :key="index1"
              :label="item1.label"
              :value="item1.value"
            ></el-option>
          </el-select>
          <el-input v-else
                    v-model="tableQuery[item.prop]"
                    :placeholder="`${item.placeholder?item.placeholder:item.label}`"/>
        </el-form-item>
      </template>
<!--      <el-form-item label="账户名">
        <el-input v-model="query.username"></el-input>
      </el-form-item>-->
      <!--表单右边的插槽-->
      <slot name="right" :data="query">

      </slot>
      <slot name="submit" :data="query">
      <el-form-item>
        <TableQueryFormItemSetting
          :formHeaders="formHeaders"
          :extraFormHeaders="extraFormHeaders"
          @changeSelect="changeSelect"
        />
        <el-button type="primary" @click="submitQuery">查询</el-button>
        <el-button type="primary" @click="clearAndRereshTable">重置</el-button>
      </el-form-item>
      </slot>
    </el-form>
</template>

<script lang="ts" setup>
import TableQueryFormItemSetting from '@/components/base/table/TableQueryFormItemSetting.vue';
import {
  reactive,
  ref,
  withDefaults,
  defineProps,
  computed,
  getCurrentInstance,
  WritableComputedRef,
  watch,
  unref,
  isRef,
  onMounted,
} from 'vue';
import { FormHeader, TableColumn } from '@/types/interface/base_interface';

const { proxy } = getCurrentInstance();
interface Props {// 需要在父组件引入自定义的@/api/uem/useTableList.ts组件，然后将其中的部分属性传过来
  query: Record<string, any>, // 查询表单对象
  loadTableList:()=>void, // 重新加载表格
  clearQuery:()=>void, // 当页面发生变化时触发的一个函数
  removeQueryField:(key:string)=>void // 移除查询条件中的某个元素
  queryFormHeaders:Array<FormHeader> // 查询表单
}
const props = withDefaults(defineProps<Props>(), {
  query: () => ({}), // 返回空对象
  formHeaders: () => new Array<FormHeader>(),
});
// 初始化时显示的表单元素
const formHeaders:FormHeader[] = [];
// 需要手动操作显示的表单元素
const extraFormHeaders:FormHeader[] = [];
// 对表单的默认显示状态进行处理
// 初始化表单
props.queryFormHeaders.forEach((item:FormHeader) => {
  if (item.show === false) { // 如果不显示，则作为扩展表单
    extraFormHeaders.push(item);
  } else {
    formHeaders.push(item);
  }
});
// const tableQuery = computed(() => JSON.parse(JSON.stringify(props.query)));
const tableQuery = computed(() => props.query); // 因为要保留引用对象地址，这里不进行深度拷贝
// const formHeaders = computed(() => JSON.parse(JSON.stringify(props.queryFormHeaders)));
// 实现查询表单的动态显示
const formHeadersVisible = ref<FormHeader[]>([]); // 定义用于显示的列
// 当列选择发生变化时，查询表单的显示数据也发生变化
const changeSelect = (columnsSelected:string[]) => {
  formHeadersVisible.value = [];
  props.queryFormHeaders.forEach((formHeader:FormHeader) => {
    if (columnsSelected.indexOf(formHeader.prop) !== -1) {
      formHeadersVisible.value.push(formHeader);
    }
  });
};
// 提交查询表单
// 说明：只提交显示的表单
const submitQuery = () => {
  // 将查询表单中已经隐藏的属性移除
  Object.keys(props.query).forEach((key:string) => {
    let result = false; // 默认该主键在查询表单中不存在
    for (let i = 0; i < formHeadersVisible.value.length; i += 1) {
      let formHeader:FormHeader = formHeadersVisible.value[i];
      if (key === (formHeader.propAsName ? formHeader.propAsName : formHeader.prop)) { // propAsName针对关联属性命名移除的判断，如department.id
        result = true;
        break;
      }
    }
    if (result === false) { // 如果在查询表单中不存在
      // 从查询条件中移除该属性
      props.removeQueryField(key);
    }
  });
  props.loadTableList();
};
// 清空查询条件并重置表格
const clearAndRereshTable = () => {
  // 清空查询条件前要处理的钩子函数
  proxy.$emit('beforeClearQuery');
  // 清空查询条件
  props.clearQuery();
  // 清空查询条件后要处理的钩子函数
  proxy.$emit('afterClearQuery');
  // 重新刷新表格
  props.loadTableList();
};
// const tableQuery = computed(() => {
//   console.log('b', props.modelValue);
//   return props.modelValue;
// });
// watch(() => tableQuery, (newVal:any, oldVal:any) => { // 开启深度监听
//   console.log('bb', newVal, tableQuery.value === newVal);
//   proxy.$emit('update:modelValue', newVal);
// }, { deep: true, immediate: true });
</script>
<style lang="scss" scoped>

</style>
